﻿import mx.utils.Delegate;
dynamic class SoundClip extends MovieClip{
	public static var M_LOADING:String = "loading_progress";
	public static var M_PLAYING:String = "playing_progress";
	public static var M_COMPLETE:String = "sound_Complete";
	
	private var $hostMc:MovieClip;
	private var $sound:Sound;
	private var _say:Say;
	private var $availab:Boolean;
	private var $playing:Boolean;
	private var $pausing:Boolean;
	private var $pausetime:Number;
	private var $timeout:Number = 150;
	private var $nowtimeout:Number = 0;
	
	private var $loadtracking:MovieClip;
	
	public function get Volume():Number {
		if (this.$availab) {
			return this.$sound.getVolume();
		}else {
			return -1;
		}
	}
	public function set Volume(value:Number) {
		if(this.$availab){
			value = Math.max(0, value);
			value = Math.min(value, 100);
			this.$sound.setVolume(value);
		}
	}
	public function get Pan():Number {
		if (this.$availab) {
			return this.$sound.getPan();
		}else {
			return Number.NaN;
		}
	}
	public function set Pan(value:Number) {
		if(this.$availab){
			value = Math.max(-100, value);
			value = Math.min(value, 100);
			this.$sound.setPan(value);
		}
	}
	/**
	 * mp3的附加信息
	 */
	public function get ID3():Object {
		return this.$sound.id3;
	}
	/**
	 * 声音是否可用
	 */
	public function get Availab():Boolean { 
		return $availab; 
	}
	/**
	 * 声音是否正在播放
	 */
	public function get Playing():Boolean { 
		return $playing; 
	}
	
	public function get Pausing():Boolean { 
		return $pausing; 
	}
	
	
	public function SoundClip(root:MovieClip) {
		initsay();
		initbroadcast();
		if (root == undefined) {
			root = this;
		}
		if (root == undefined) {
			_say.msay("sound Not binding a MovieClip.");
		}
		this.$hostMc = root;
	}
	
	private function initbroadcast():Void{
		AsBroadcaster.initialize(this);
	}
	
	public function loadSound(link:String, url:String) {
		if ($sound != undefined) {
			this.$sound.stop();
		}
		this.$sound = new Sound(this.$hostMc);
		this.$playing = false;
		this.$availab = false;
		this.$pausing = false;
		
		
		if (url != undefined && url != "") {
			this._say.msay("load sound:"+url);
			this.$sound.loadSound(url,false);
			this.$sound.onLoad = Delegate.create(this, this.onloadedsound);
			this.startTrackingSound();
			this.$sound.onSoundComplete = Delegate.create(this, this.onSoundCompletedFun);
		}else if (link != undefined && link != "") {
			this._say.msay("link sound:"+link);
			this.$sound.attachSound(link);
			this.startTrackingSound();
			this.onloadedsound(true);
			this.broadcaseLoadingMsg(100, 100, "");
			this.$sound.onSoundComplete = Delegate.create(this, this.onSoundCompletedFun);
		}else {
			_say.esay("未设置声音加载位置.");
		}
	}
	private function onSoundCompletedFun() {
		this.$playing = false;
		this.$pausing = false;
		this.broadcastMessage(M_COMPLETE, this);
	}
	private function onloadedsound(success:Boolean) {
		if (success) {
			this.$availab = true;
			
		}else {
			this.$availab = false;
			this.stopTrackingSound();
			//this.broadcastMessage(M_LOADING, this, -1, -1, "load error,check sound url");
			this.broadcaseLoadingMsg( -1, -1, "load error,check sound url");
		}
	}
	/**
	 * 广播loading消息
	 * @param	ll 已加载
	 * @param	tt total
	 * @param	msg 消息 
	 */
	private function broadcaseLoadingMsg(ll, tt, msg) {
		this.broadcastMessage(M_LOADING, this, ll, tt, msg);
		this[M_LOADING](this, ll, tt, msg);
	}
	/**
	 * 广播播放进度消息 
	 * @param	ll 已播放
	 * @param	tt total
	 * @param	msg 消息 
	 */
	private function broadcasePlayingMsg(ll, tt, msg) {
		this.broadcastMessage(M_PLAYING, this, ll, tt, msg);
		this[M_PLAYING](this, ll, tt, msg);
	}
	/**
	 * 广播声音完成情况
	 * @param	msg 消息
	 */
	private function broadcaseCompleteMsg(msg) {
		this.broadcaseMessage(M_COMPLETE, this, msg);
		this[M_COMPLETE](this, msg);
	}
	/**
	 * 开始监控声音（加载，播放等信息）
	 */
	private function startTrackingSound() {
		if (this.$loadtracking != undefined) {
			this.$loadtracking.removeMovieClip();
		}
		this.$loadtracking=this.$hostMc.createEmptyMovieClip("___SoundTracking" + (new Date()).getTime().toString().substring(3), 10);
		this.$loadtracking.onEnterFrame = Delegate.create(this, this.SoundTrackingFun);
	}
	/**
	 * 停止监控声音（加载，播放等信息）
	 */
	private function stopTrackingSound() {
		if (this.$loadtracking != undefined) {
			delete this.$loadtracking.onEnterFrame;
			this.$loadtracking.removeMovieClip();
		}
	}
	/**
	 * 监控声音
	 */
	private function SoundTrackingFun() {
		if (!this.$availab) {
			var ll:Number = this.$sound.getBytesLoaded();
			var tt:Number = this.$sound.getBytesTotal();
			if (tt == undefined || tt <= 0 ) {
				this.$nowtimeout++;
				if (this.$nowtimeout > this.$timeout) {
					this._say.esay("load sound timeout!");
					//this.broadcastMessage(M_LOADING, this, -1, -1, "load mp3 time out!");
					this.broadcaseLoadingMsg( -1, -1, "load mp3 time out!");
					this.stopTrackingSound();
				}else {
					this.broadcastMessage(M_LOADING, this, ll, tt);
				}
			}
		}else {
			if (this.$playing) {
				var pl:Number = this.$sound.position;
				var tl:Number = this.$sound.duration;
				this.broadcasePlayingMsg(pl, tl, "");
			}
		}
	}
	
	/**
	 * 开始播放声音 （开始播放暂停了的声音）
	 * @param	offset	播放起启位置
	 * @param	loop	播放循环次数
	 */
	public function start(offset:Number, loop:Number) {
		//trace(arguments)
		if (this.$availab) {
			offset = ((offset == undefined)? 0:offset);
			loop = ((offset == undefined)? 1:loop);
			
			if (this.$pausing) {
				this.$sound.start(this.$pausetime/1000, loop);
				this.$pausing = false;
				this.$playing = true;
			}else{
				this.stop();
				this.$sound.start(offset, loop);
				this.$pausing = false;
				this.$playing = true;
			}
			return true;
		}else {
			this._say.esay("播放不成功！声音还未准备好。");
			return false;
		}
	}
	/**
	 * 暂停播放(对未开始播放的声音无效)
	 * @param	loop 再次开始时的loop次数
	 */
	public function pause(loop:Number) {
		if (loop <= 0 || loop == undefined) {
			loop = 1;
		}
		if (this.$availab) {
			if (this.$pausing) {
				this.start(this.$pausetime,loop);
				this.$pausetime = 0;
			}else {
				if(this.$playing){
					this.$pausetime = this.$sound.position;
					this.stop();
					this.$pausing = true;
				}
			}
		}
	}
	/**
	 * 停止播放
	 */
	public function stop() {
		this.$sound.stop();
		this.$playing = false;
		this.$pausing = false;
	}
	
	
	
	private function initsay() {
		_say = new Say("SD");
		_say.addListener(this);
		this[Say.M_SAY] = this.sayfun;
	}
	private function sayfun(o) {
		trace(o);
	}
	
	
}